package com.guaoran.source.curatorzk;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;

import java.util.ArrayList;
import java.util.List;

/**
 * @author : 孤傲然
 * @Description :
 * @date :2018/6/14 10:11
 */
public class ServiceDiscoveryImpl implements IServiceDiscovery {
    private CuratorFramework curatorFramework = ZookeeperConfig.initCuratorFramework();
    private List<String> serviceChildrens = new ArrayList<>();
    /**
     * 根据服务名称获得对应的调用地址
     * @param serviceName
     * @return
     */
    @Override
    public String discovery(String serviceName) {
        String servicePath = ZookeeperConfig.ZK_REGISTER_PATH + "/" + serviceName;
        try {
            //根据服务名称获得子节点
            serviceChildrens = curatorFramework.getChildren().forPath(servicePath);
        } catch (Exception e) {
            throw new RuntimeException("获取子节点异常");
        }
        //监听服务子节点变化
        registerWatcher(servicePath);
        //使用负载均衡机制：随机获得一个子节点进行调用
        ILoadBanalce loadBanalce = new RandomLoadBanalce();
        return loadBanalce.selectHost(serviceChildrens);
    }

    /**
     * 监听子节点变化
     * @param servicePath
     */
    private void registerWatcher(String servicePath){
        PathChildrenCache pathChildrenCache = new PathChildrenCache(curatorFramework,servicePath,true);
        PathChildrenCacheListener listener = new PathChildrenCacheListener() {
            @Override
            public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
                //监听子节点变化，当子节点发生添加、更新和删除操作后重新获取子节点
                serviceChildrens = curatorFramework.getChildren().forPath(servicePath);
            }
        };
        pathChildrenCache.getListenable().addListener(listener);
        try {
            pathChildrenCache.start();
        } catch (Exception e) {
            throw new RuntimeException("监听子节点变化 异常"+e);
        }

    }
}
